import { GLTF } from "three/examples/jsm/loaders/GLTFLoader.ts";
import { Animate, Viewer } from "../Viewer";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.ts";
import * as THREE from 'three'
import { clone } from "three/examples/jsm/utils/SkeletonUtils.js";
import { Object3DExtends } from '../../types'

export class BaseModel {
    protected viewer!: Viewer
    public gltf: GLTF
    public object: THREE.Group
    public clock: THREE.Clock
    public animaIndex: number = -1
    public mixer!: THREE.AnimationMixer
    public animaObject!: Animate
    public isSaveMaterial: boolean = false;

    // 原始模型材质
    public originMaterials: THREE.Material[] = [];

    constructor(viewer: Viewer, gltf: GLTF) {
        this.viewer = viewer
        this.gltf = gltf
        this.object = gltf.scene || gltf

        this.clock = new THREE.Clock()
    }

    public setScalc(x: number, y?: number, z?: number) {
        this.object.scale.set(x, y || x, z || x)
    }

    public getLength() {
        const box = new THREE.Box3().setFromObject(this.object)
        return box.getSize(new THREE.Vector3()).length()
    }

    // 设置动画
    public startAnima(i = 0) {
        this.animaIndex = i

        if (!this.mixer) this.mixer = new THREE.AnimationMixer(this.object)
        if (this.gltf.animations.length < 1) return
        this.mixer.clipAction(this.gltf.animations[i]).play()

        this.animaObject = {
            content: this,
            fun: this.updateAnima
        }
    }

    private updateAnima(e: any) {
        e.mixer.update(e.clock.getDelta());
    }

    // 克隆模型
    public cloneModel([x, y, z] = [0, 0, 0]) {
        const newScene = { ...this.gltf }
        const newModel = clone(this.object)
        newModel.position.set(x, y, z)
        this.viewer.scene.add(newModel)
        newScene.scene = newModel as any
        return new BaseModel(this.viewer, newScene)
    }

    // 开启模型的阴影 数组中移除阴影
    public openCastShadow(name = []) {
        this.gltf.scene.traverse((model: Object3DExtends) => {
            if (model.isMesh && !name.includes(model.name as never)) {
                model.frustumCulled = false
                model.castShadow = true
            }
        })
    }

    // 设置模型颜色
    public setColor(color: 'yellow', opacity = 0.5) {
        if (!this.isSaveMaterial) this.originMaterials = []
        this.gltf.scene.traverse((model: Object3DExtends) => {
            if (model.isMesh) {
                if (!this.isSaveMaterial) this.originMaterials.push(model.material as THREE.Material)
                model.material = new THREE.MeshPhongMaterial({
                    side: THREE.DoubleSide,
                    color: new THREE.Color(color),
                    transparent: true,
                    opacity: opacity,
                    depthTest: true,
                    depthWrite: true
                })
            }
        })
    }

    // 设置模型材质
    public setMaterial(material = new THREE.MeshBasicMaterial()) {
        if (!this.isSaveMaterial) this.originMaterials = []
        this.gltf.scene.traverse((model: Object3DExtends) => {
            if (model.isMesh) {
                if (!this.isSaveMaterial) this.originMaterials.push(model.material as THREE.Material)
                model.material = material
            }
        })
        this.isSaveMaterial = true
    }

    // 还原模型材质
    public setDefaultMerterial() {
        let i = 0
        this.gltf.scene.traverse((model: Object3DExtends) => {
            if (model.isMesh) {
                model.material = this.originMaterials[i]
                i++
            }
        })
    }
}